"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const week_1 = require("./describers/week");
const moment = require("moment");
const matchTime = (mm, n) => {
    const minute = mm.minute();
    const hour = mm.hour();
    return n.minutes.indexOf(minute) >= 0 && n.hours.indexOf(hour) >= 0;
};
const matchDate = (mm, n) => {
    const date = mm.date();
    const month = mm.month() + 1;
    const week = mm.weekday();
    if (n.daysAnded) {
        return n.dates.indexOf(date) >= 0 &&
            n.months.indexOf(month) >= 0 &&
            n.weekdays.indexOf(week) >= 0;
    }
    else {
        return n.months.indexOf(month) >= 0 &&
            (n.dates.indexOf(date) >= 0 || n.weekdays.indexOf(week) >= 0);
    }
};
const match = (mm, n) => {
    return matchTime(mm, n) && matchDate(mm, n);
};
const MINUTES_OF_YEAR = 366 * 24 * 60;
class Iterator {
    constructor(normalized, from = new Date()) {
        this.normalized = normalized;
        this.dayIndex = 0;
        this.monthIndex = 0;
        this.minuteIndex = 0;
        this.hourIndex = 0;
        this.year = 0;
        this.mm = moment(from);
        this.year = this.mm.year();
    }
    isMatch() {
        return match(this.mm, this.normalized);
    }
    isMatchTime() {
        return matchTime(this.mm, this.normalized);
    }
    isMatchDate() {
        return matchDate(this.mm, this.normalized);
    }
    moveToTimeAlign(hourStart, minuteStart) {
        for (let h = hourStart; h <= 23; h++) {
            this.mm.hour(h);
            for (let m = h == hourStart ? minuteStart : 0; m <= 59; m++) {
                this.mm.minute(m);
                if (this.isMatchTime()) {
                    return;
                }
            }
        }
        this.stepDay();
        this.moveToDateAlign();
        this.moveToTimeAlign(0, 0);
    }
    moveToDateAlign() {
        while (!this.isMatchDate()) {
            this.stepDay();
        }
        this.mm.hour(0).minute(0);
    }
    stepDay() {
        this.mm.add(1, 'day');
    }
    step() {
        this.mm.add(1, 'minute');
    }
    next() {
        if (!this.isMatchDate()) {
            this.moveToDateAlign();
        }
        if (!this.isMatchTime()) {
            this.moveToTimeAlign(this.mm.hour(), this.mm.minute());
        }
        const date = this.mm.toDate();
        this.mm.add(1, "minute");
        return date;
    }
}
exports.Iterator = Iterator;
function nextDate(normalizeCrontab, fromDate) {
    const iter = new Iterator(normalizeCrontab, fromDate);
    return iter.next();
}
exports.nextDate = nextDate;
const formatString = 'YYYY-MM-DD HH:mm';
function format(d, withWeek = false) {
    const dateString = moment(d).format(formatString);
    return withWeek ? `${dateString} (${week_1.numberToWeekHans(d.getDay())})` : dateString;
}
exports.format = format;
